package com.yesstech.generate.document.service.impl;

import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder;
import com.yesstech.generate.document.service.GenerateDocumentService;
import com.yesstech.generate.document.vo.GenerateDocumentVo;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.swagger.models.parameters.HeaderParameter;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.entity.ContentLengthStrategy;
import org.apache.http.entity.ContentType;
import org.apache.tomcat.util.http.HeaderUtil;
import org.springframework.http.ContentDisposition;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 生成文档服务
 *
 * @author pengzhikang
 * @date 2025/3/12 16:52
 * @since 1.0.0
 */
@Service
public class GenerateDocumentServiceImpl implements GenerateDocumentService {

    @Override
    public void generateDocument(GenerateDocumentVo generateDocumentVo, HttpServletResponse response) {
        try {
            String zipName = generateDocumentVo.getFileName() + ".zip";

            byte[] bytes = generate(generateDocumentVo, zipName);

            response.reset();
            response.addHeader("Content-Length", String.valueOf(bytes.length));
            response.setHeader("Content-Disposition", ContentDisposition.attachment().filename(zipName).build().toString());
            response.setContentType(ContentType.APPLICATION_OCTET_STREAM.withCharset(StandardCharsets.UTF_8).toString());

            IOUtils.write(bytes, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private byte[] generate(GenerateDocumentVo generateDocumentVo, String zipName) throws IOException {
        try (FileSystem fileSystem = MemoryFileSystemBuilder.newEmpty().build()) {
            Path path = fileSystem.getPath(generateDocumentVo.getFileName());

            Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
                    .withMarkupLanguage(generateDocumentVo.getMarkupLanguage())
                    .build();

            Swagger2MarkupConverter.from(new URL(generateDocumentVo.getUrl()))
                    .withConfig(config)
                    .build()
                    .toFolder(path);

            Path zipFilePath = Paths.get(zipName);
            zipArchiveFolder(path, zipFilePath);

            return Files.readAllBytes(zipFilePath);
        }
    }

    /**
     * zip存档文件夹
     *
     * @param folderPath  文件夹路径
     * @param zipFilePath zip文件路径
     * @throws IOException IOException
     * @author pengzhikang
     * @date 2025/03/12 20:41
     */
    public void zipArchiveFolder(Path folderPath, Path zipFilePath) throws IOException {
        try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(Files.newOutputStream(zipFilePath))) {
            zos.setEncoding(StandardCharsets.UTF_8.name());
            zos.setUseZip64(Zip64Mode.AsNeeded);

            Files.walk(folderPath)
                    .filter(path -> !Files.isDirectory(path))
                    .forEach(path -> {
                        ZipArchiveEntry zae = new ZipArchiveEntry(folderPath.relativize(path).toString());
                        try {
                            zos.putArchiveEntry(zae);
                            Files.copy(path, zos);
                            zos.closeArchiveEntry();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
        }
    }


}
